package jmm;

/**
 * 描述：     演示可见性带来的问题
 */
public class FieldVisibility {

//    int a = 1;
//    int b = 2;

    volatile int a = 1;
    volatile int b = 2;

    private void change() {
        a = 3; // 80
        b = a;
    }

    /**
     *  b=2,a=1  有 大概率: threadPrint先启动,且执行完成后,threadChange才启动
     *  b=3,a=1  有 极小概率: threadChange启动,将a=3,b=3在"localCache"中执行完成.然后threadPrint启动.由于可见性带来的问题,b=3,a=3只是在
     *                                        threadChange线程的"localCache"中完成,其中b=3被及时写出到主存,而a=3并没有被及时写出到主存中.导致threadPrint在
     *                                        打印时读取到b=3,a=1.若果a,b都用volatile关键字修饰,就不会出现b=3,a=1这种情况了.但其它三种情况还是会出现的.
     *  b=2,a=3  有 稍大概率: threadChange先启动,执行到a=3,然后将a=3写入到主存,然后cpu切换到threadPrint,打印的就是b=2,a=3
     *  b=3,a=3  有 大概率: threadChange先启动,且执行完成后,threadPrint才启动
     */
    private void print() {
        System.out.println("b=" + b + ",a=" + a);
    }

    public static void main(String[] args) {
        while (true) {
            FieldVisibility fieldVisibility = new FieldVisibility();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    fieldVisibility.change();
                }
            },"threadChange").start();

            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    fieldVisibility.print();
                }
            },"threadPrint").start();
        }
    }
}
